﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeanboxSoftware.BeanMap
{
  public static class MapExtensions
  {
    public static Map<K, V> ToMap<T, K, V>(
      this IEnumerable<T> list,
      Func<T, K> keyGen,
      Func<T, V> valueGen)
    {
      var result = new Map<K, V>();

      foreach (var item in list)
      {
        result[keyGen(item)] = valueGen(item);
      }

      return result;
    }

    public static Map<K1, K2, V> ToMap<T, K1, K2, V>(
      this IEnumerable<T> list,
      Func<T, K1> key1Gen,
      Func<T, K2> key2Gen,
      Func<T, V> valueGen)
    {
      var result = new Map<K1, K2, V>();

      foreach (var item in list)
      {
        result[key1Gen(item), key2Gen(item)] = valueGen(item);
      }

      return result;
    }

    public static Map<K1, K2, K3, V> ToMap<T, K1, K2, K3, V>(
      this IEnumerable<T> list,
      Func<T, K1> key1Gen,
      Func<T, K2> key2Gen,
      Func<T, K3> key3Gen,
      Func<T, V> valueGen)
    {
      var result = new Map<K1, K2, K3, V>();

      foreach (var item in list)
      {
        result[key1Gen(item), key2Gen(item), key3Gen(item)] = valueGen(item);
      }

      return result;
    }
  }

  public partial class Map<K, V> : Internal.MapBase<Func<K, V>, V, K, V>, IMap<K, V>
  {
    public static Map<K, V> From<T>(IEnumerable<T> list, Func<T, K> keyGen, Func<T, V> valueGen)
    {
      return list.ToMap(keyGen, valueGen);
    }
  }

  public partial class Map<K1, K2, V> : Internal.MapBase<Func<K1, K2, V>, V, K1, IDictionary<K2, V>>, IMap<K1, K2, V>
  {
    public static Map<K1, K2, V> From<T>(IEnumerable<T> list, Func<T, K1> key1Gen, Func<T, K2> key2Gen, Func<T, V> valueGen)
    {
      return list.ToMap(key1Gen, key2Gen, valueGen);
    }
  }

  public partial class Map<K1, K2, K3, V> : Internal.MapBase<Func<K1, K2, K3, V>, V, K1, IDictionary<K2, IDictionary<K3, V>>>, IMap<K1, K2, K3, V>
  {
    public static Map<K1, K2, K3, V> From<T>(IEnumerable<T> list, Func<T, K1> key1Gen, Func<T, K2> key2Gen, Func<T, K3> key3Gen, Func<T, V> valueGen)
    {
      return list.ToMap(key1Gen, key2Gen, key3Gen, valueGen);
    }
  }
}
